"""
Copyright (c) 2022 Huawei Technologies Co.,Ltd.

openGauss is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:

          http://license.coscl.org.cn/MulanPSL2

THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details.
"""
"""
Case Type   : 故障&可靠性测试
Case Name   : 事务操作产生日志，删除对应新增xlog文件，重启数据库失败
Create At   : 2020/07/20
@zou_jialiang0505328114
Description :
    1. 修改checkpoint_segments、checkpoint_timeout参数，重启数据库使其生效；
    2. 切换xlog；
    3. 执行数据库插入脚本，产生xlog文件；
    4. 获取当前xlogfilename，并删除物理文件（通过MV实现）
    5. 重启数据库（预期失败）；
    6. 恢复xlogfile、恢复checkpoint_segments、checkpoint_timeout参数，并重启使其生效；
    7、检查数据库状态
Expect      :
    1、修改参数成功，并生效；
    2、切换xlog成功；
    3、完成数据插入，并产生xlog；
    4、获取到当前xlogfile并通过MV删除成功；
    5、重启数据库失败；
    6、恢复成功，重启成功；
    7、数据库状态正常；
History     :
    Modified: 2020/12/19  modified by @wan005,修改Constant用法
    Modified: 2020/12/22  modified by @wan005,
        2020-12-21 20:03:15 commit 0 last mr版本删除xlog后数据库状态正常
    Modified: 2020/1/7   modified by @peilinqian，优化整个脚本；
        2021-01-05 20:06:16 commit 0 last mr 删除xlog后数据库状态非正常
    Modified: 2020/2/26  modified by @peilinqian，优化脚本，增加必要打印信息;xlog删除数据库重启断言优化；
"""
import os
import time
import unittest

from testcase.utils.Common import Common
from testcase.utils.CommonSH import CommonSH
from testcase.utils.CommonSH import RestartDbCluster
from testcase.utils.Constant import Constant
from testcase.utils.Logger import Logger
from yat.test import Node
from yat.test import macro


class Deletaduit(unittest.TestCase):
    nodes_tuple = ('PrimaryDbUser', 'Standby1DbUser', 'Standby2DbUser')

    @RestartDbCluster(*nodes_tuple)
    def setUp(self):
        self.log = Logger()
        self.log.info('----Opengauss_Reliability_Dbsys_Case201 start----')
        self.pri_root = Node(node='PrimaryRoot')
        self.xlogpath = ''
        self.new_xlogpath = os.path.join(macro.DB_INSTANCE_PATH,
                                         'pg_xlog',
                                         'newxlog')
        self.pri_sh = CommonSH('PrimaryDbUser')
        self.Common = Common()
        self.Constant = Constant()

    def test_startdb(self):
        self.log.info('----修改相关参数,并重启数据库----')
        msg = self.pri_sh.executeGsguc('reload',
                                       self.Constant.GSGUC_SUCCESS_MSG,
                                       'checkpoint_segments = 1600')
        self.assertTrue(msg)
        msg = self.pri_sh.executeGsguc('reload',
                                       self.Constant.GSGUC_SUCCESS_MSG,
                                       'checkpoint_timeout = 60min')
        self.assertTrue(msg)
        self.log.info('----show参数----')
        show_result = self.pri_sh.executDbSql('show checkpoint_segments;'
                                              'show checkpoint_timeout;')
        self.log.info(show_result)

        self.log.info('----切换xlog----')
        self.pri_sh.executDbSql('select pg_switch_xlog();')
        switch_sql = 'select pg_xlogfile_name(pg_current_xlog_location());'
        self.pri_sh.executDbSql(switch_sql)

        self.log.info('----创建数据表，并插入数据----')
        t_tablename = 't_Dbsys_Case201'
        self.sql = f'''drop table if exists {t_tablename};
                       create table {t_tablename}(id int);
                       begin 
                       for i in 1..999 loop
                       insert into {t_tablename} values(i);
                       end loop;
                       end;
                       select count(1) from t_Dbsys_Case201 ;'''
        ddl_result = self.pri_sh.executDbSql(self.sql)
        self.log.info(ddl_result)

        self.log.info('---- 获取当前xlogfilename----')
        current_sql = 'select pg_xlogfile_name(pg_current_xlog_location());'
        xlog_filename = self.pri_sh.executDbSql(current_sql)
        self.log.info(xlog_filename)
        xlog_file = xlog_filename.splitlines()[2].split(' ')[1]
        self.xlogpath = os.path.join(macro.DB_INSTANCE_PATH,
                                     'pg_xlog',
                                     xlog_file)

        self.log.info('---- 删除xlogfile----')
        mv_cmd = f'mv {self.xlogpath} {self.new_xlogpath}'
        self.log.info(mv_cmd)
        self.pri_root.sh(mv_cmd)
        ls_cmd = f'ls -lt {os.path.dirname(self.xlogpath)} |head -5'
        self.log.info(self.pri_root.sh(ls_cmd).result())

        self.log.info('---- 重启数据库----')
        is_stop = self.pri_sh.stopDbCluster()
        self.assertTrue(is_stop)
        is_started = self.pri_sh.startDbCluster()
        if is_started:
            status = self.pri_sh.getDbClusterStatus('status')
            self.assertTrue(status)

        self.log.info('---- 恢复xlogfile----')
        mv_cmd = f'mv {self.new_xlogpath} {self.xlogpath}'
        self.log.info(mv_cmd)
        self.pri_root.sh(mv_cmd)
        ls_cmd = f'ls -lt {os.path.dirname(self.xlogpath)} |head -5'
        self.log.info(self.pri_root.sh(ls_cmd).result())

        time.sleep(10)
        self.log.info('---- 查询主备状态----')
        self.pri_sh.getDbClusterStatus('status')

        self.log.info('---- 重启数据库----')
        is_stop = self.pri_sh.stopDbCluster()
        self.assertTrue(is_stop)
        is_started = self.pri_sh.startDbCluster()
        self.assertTrue(is_started)

        self.log.info('----验证数据库功能正常----')
        ddl_result = self.pri_sh.executDbSql(self.sql)
        self.log.info(ddl_result)

    def tearDown(self):
        self.log.info('----teardown----')
        self.log.info('----恢复xlogfile----')
        mv_cmd = f'mv {self.new_xlogpath} {self.xlogpath}'
        self.log.info(mv_cmd)
        self.pri_root.sh(mv_cmd)
        ls_cmd = f'ls -lt {os.path.dirname(self.xlogpath)} |head -5'
        self.log.info(self.pri_root.sh(ls_cmd).result())

        self.log.info('----修改相关参数,并重启数据库----')
        self.pri_sh.executeGsguc('reload', self.Constant.GSGUC_SUCCESS_MSG,
                                 'checkpoint_segments = 64')
        self.pri_sh.executeGsguc('reload', self.Constant.GSGUC_SUCCESS_MSG,
                                 'checkpoint_timeout = 15min')
        self.log.info('----show参数----')
        show_result = self.pri_sh.executDbSql('show checkpoint_segments;'
                                              'show checkpoint_timeout;')
        self.log.info(show_result)

        self.log.info('----Opengauss_Reliability_Dbsys_Case201 finish----')
